package com.newlink.building.common_base.base

import android.app.Activity
import android.app.ProgressDialog
import android.bluetooth.BluetoothAdapter
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.graphics.Color
import android.graphics.PixelFormat
import android.graphics.drawable.ColorDrawable
import android.os.Build
import android.os.Bundle
import android.util.Log
import android.util.SparseArray
import android.view.*
import android.widget.LinearLayout
import android.widget.TextView
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.Toolbar
import com.afollestad.materialdialogs.color.CircleView
import com.google.android.material.snackbar.Snackbar
import com.newlink.building.common_base.R
import com.newlink.building.common_base.api.Base_ApiEnv
import com.newlink.building.common_base.constant.Base_Constant
import com.newlink.building.common_base.event.Base_KcpChangeEvent
import com.newlink.building.common_base.event.MessageEvent
import com.newlink.building.common_base.event.Base_NetworkChangeEvent
import com.newlink.building.common_base.event.OpenDoorResultBean
import com.newlink.building.common_base.event.TYPE_APP_BLE_OPEN_DOOR_RESULT
import com.newlink.building.common_base.event.TYPE_APP_OPEN_BT
import com.newlink.building.common_base.event.TYPE_APP_SHOW_LOADING
import com.newlink.building.common_base.event.TYPE_APP_SHOW_WAITING_DIALOG
import com.newlink.building.common_base.model.bean.CountryCodeBean
import com.newlink.building.common_base.model.bean.KcpInfoData
import com.newlink.building.common_base.model.bean.MqttData
import com.newlink.building.common_base.model.bean.SipInfo
import com.newlink.building.common_base.model.bean.UserInfoData
import com.newlink.building.common_base.model.bean.UserInfoResp
import com.newlink.building.common_base.receiver.Base_NetworkChangeReceiver
import com.newlink.building.common_base.utils.*
import com.newlink.building.common_base.widget.ToastSettingDialog
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
import java.util.*
import kotlin.math.pow


/**
 * Created by xiaodong on 2022/7/25.
 */
abstract class NL_BaseActivity : AppCompatActivity() {

    companion object {
        const val RESULT_ERROR: Int = -2
    }

    /**
     * token
     */
    protected var accessToken: String by Base_Preference(Base_Constant.TOKEN_KEY, "")

    /**
     * kcp connect id
     */
    protected var kcpConnectId: Int by Base_Preference(Base_Constant.KCP_CONNECT_ID_KEY, -1)

    /**
     * destDeviceId
     */
    protected var kcpDestDeviceId: String by Base_Preference(Base_Constant.KCP_DEST_DEVICE_ID, "")

    /**
     * kcp userId
     */
    protected var cUserId: String by Base_Preference(Base_Constant.KCP_USER_ID_KEY, "")


    protected var countryCode: String by Base_Preference(Base_Constant.COUNTRY_CODE_KEY, "")

    /**
     * userId
     */
    protected var userId: Long by Base_Preference(Base_Constant.USER_ID_KEY, 0L)

//    /**
//     * prjId 项目id
//     */
//    protected var prjId: String by Preference(Constant.PRJ_ID_KEY, "")

    /**
     * 声网Id
     */
    protected var agoraId: Int by Base_Preference(Base_Constant.AGORA_ID_KEY, 0)

    protected var agoraAppId: String by Base_Preference(Base_Constant.AGORA_App_ID_KEY, "")

    protected var bluetoothOpenDoor: Boolean by Base_Preference(Base_Constant.BLUETOOTH_OPEN_DOOR, false)

    /**
     * server type
     * 0 fsds,
     * 1 室内机/门禁,
     *
     */
    protected var serverType: Int by Base_Preference(Base_Constant.KCP_SERVER_TYPE_KEY, 0)

    protected var useBluetooth: Boolean by Base_Preference(Base_Constant.BT_OPEN_DOOR_KEY, false)

    protected var lastBleAddr: String by Base_Preference(Base_Constant.BT_OPEN_DOOR_LAST_ADDR, "")

    protected var maxUserCount: Int by Base_Preference(Base_Constant.MAX_USER_COUNT, 4)

    protected var userCategory: Int by Base_Preference(Base_Constant.USER_CATEGORY, 1)

    /**
     * 用户详情
     */
    protected var userInfoData: UserInfoData by Base_Preference(
        Base_Constant.USER_INFO_KEY,
        UserInfoData()
    )

    protected var mqttDataCache: MqttData by Base_Preference(
        Base_Constant.MQTT_INFO_KEY,
        MqttData()
    )

    protected var userInfoResp: UserInfoResp by Base_Preference(
        Base_Constant.USER_INFO_RESP_KEY,
        UserInfoResp()
    )

    /**
     * Kcp参数
     */
    protected var kcpInfoData: KcpInfoData by Base_Preference(
        Base_Constant.KCP_INFO_KEY,
        KcpInfoData()
    )

    /**
     * Sip详情
     */
    protected var sipInforData: SipInfo by Base_Preference(
        Base_Constant.SIP_INFO_KEY,
        SipInfo()
    )


    /**
     * check login
     */
    protected var isLogin: Boolean by Base_Preference(Base_Constant.LOGIN_KEY, false)

    protected var tokenStart: Long by Base_Preference(Base_Constant.TOKEN_START_KEY, 0L)

    /**
     * 检测是否为主账号
     */
    protected var isPrimaryAccount: Boolean by Base_Preference(Base_Constant.PRIMARY_ACCOUNT_KEY, false)

    protected var isFirstUse: Boolean by Base_Preference(Base_Constant.FIRST_USE, true)

    /**
     * 登录手机号
     */
    protected var phoneNumber: String by Base_Preference(Base_Constant.USERNAME_KEY, "")


    protected var mqttServerUrl: String by Base_Preference(Base_Constant.MQTT_ADDR_KEY, "")

    protected var mqttServerPort: String by Base_Preference(Base_Constant.MQTT_PORT_KEY, "")

    protected var mqttUName: String by Base_Preference(Base_Constant.MQTT_NAME_KEY, "")

    protected var mqttUPassword: String by Base_Preference(Base_Constant.MQTT_PASSWORD_KEY, "")

    protected var emailAccount: String by Base_Preference(Base_Constant.REMEMBER_EMAIL_ACCOUNT, "")

    protected var sipAccount: String by Base_Preference(Base_Constant.REMEMBER_SIP_ACCOUNT, "")

    protected var pwdSaved: String by Base_Preference(Base_Constant.REMEMBER_PWD_VALUE, "")

    protected var isSaveAccountAndPwd: Boolean by Base_Preference(
        Base_Constant.REMEMBER_SAVE_ACCOUNT_PWD,
        true
    )

    protected var flsServer: String by Base_Preference(Base_Constant.FLS_SERVER, "")

    protected var shakeLevel: Int by Base_Preference(Base_Constant.SHAKE_LEVEL, 2)


    /**
     * SIP线路
     */
    protected var sipLine: String by Base_Preference(Base_Constant.SIP_LINE, "")

    /**
     * 缓存上一次的网络状态
     */
    protected var hasNetwork: Boolean by Base_Preference(Base_Constant.HAS_NETWORK_KEY, true)

    /**
     * 缓存上一次Kcp的网络状态
     */
    protected var hasKcpNetwork: Boolean by Base_Preference(Base_Constant.HAS_KCP_NETWORK_KEY, true)

    /**
     * api env环境配置
     */
    protected var api_env: Int by Base_Preference(Base_Constant.API_ENV, -1)

    /**
     * api env环境配置
     */
    protected var api_env_url: String by Base_Preference(Base_Constant.API_ENV_URL, "")

    /**
     * api env自定义url
     */
    protected var api_env_url_custom: String by Base_Preference(
        Base_Constant.API_ENV_URL_CUSTOM,
        Base_ApiEnv.CUSTOM.apiUrl
    )

    protected var mAllCountryList: MutableList<CountryCodeBean> by Base_Preference(
        Base_Constant.COUNTRY_LIST,
        mutableListOf()
    )

    protected var mDefaultCountryBean: CountryCodeBean by Base_Preference(
        Base_Constant.COUNTRY_DEFAULT,
        CountryCodeBean("US/CA", "United States/Canada", "1")
    )

    /**
     * 项目id
     */
    protected var projectId: String by Base_Preference(Base_Constant.PRJ_ID_KEY, "")

    /**
     * 网络状态变化的广播
     */
    protected var mNetworkChangeReceiver: Base_NetworkChangeReceiver? = null

    /**
     * theme color
     */
    protected var mThemeColor: Int = SettingUtil.getColor()

    /**
     * 提示View
     */
    protected lateinit var mTipView: View
    protected lateinit var mTipMessage: TextView
    protected lateinit var mWindowManager: WindowManager
    protected lateinit var mLayoutParams: WindowManager.LayoutParams
    protected var toastSettingDialog: ToastSettingDialog? = null
    private lateinit var enableBluetoothLauncher: ActivityResultLauncher<Intent>
    private var isCheckingBtEnabled = false

    /**
     * 布局文件id
     */
//    protected abstract fun attachLayoutRes(): Int
    protected abstract fun attachLayoutRes(): View?

    /**
     * 初始化数据
     */
    abstract fun initData()

    /**
     * 初始化 View
     */
    abstract fun initView()

    open fun bindPresenterAndView() {}

    /**
     * 开始请求
     */
    open fun start() {}

    /**
     * 是否使用 EventBus
     */
    open fun useEventBus(): Boolean = true

    /**
     * 是否允许字体不跟随系统缩放,默认不随系统字体改变
     */
    open fun allowFontScale(): Boolean = true

    /**
     * 是否需要显示 TipView
     */
    open fun enableNetworkTip(): Boolean = true

    /**
     * 无网状态—>有网状态 的自动重连操作，子类可重写该方法
     */
    open fun doReConnected() {
        start()
    }

    open fun onBluetoothEnabledResult(isEnabled: Boolean) {

    }

    /**
     *恢复实例状态
     */
    open fun initRestoreInstanceState(savedInstanceState: Bundle) {}

    override fun onCreate(savedInstanceState: Bundle?) {
        ScreenAdapter.match(this, Base_Constant.SCREEN_DESIGN_SIZE)
        window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN)
        // AutoDensityUtil.setCustomDensity(this, App.instance)
        super.onCreate(savedInstanceState)
//        if (attachLayoutRes() > 0) {
//            setContentView(attachLayoutRes())
//        }
        if (attachLayoutRes() != null) {
            setContentView(attachLayoutRes())
        }
        if (savedInstanceState != null) {
            initRestoreInstanceState(savedInstanceState)
        }
        val llTitleBarBack = findViewById<LinearLayout>(R.id.ll_title_bar_back)
        llTitleBarBack?.setOnClickListener { finish() }
        if (useEventBus()) {
            EventBus.getDefault().register(this)
        }
        enableBluetoothLauncher =
            registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
                if (result.resultCode == Activity.RESULT_OK) {
                    // 用户同意开启蓝牙
                    NLog.e("toggle bluetooth true")
                    onBluetoothEnabledResult(true)
                } else {
                    // 用户拒绝开启蓝牙
                    NLog.e("toggle bluetooth false")
                    onBluetoothEnabledResult(false)
                }
                isCheckingBtEnabled = false
            }
        registerReceiver()
        bindPresenterAndView()
        initTipView()
        initData()
        initView()
        start()
    }

//    override fun getResources(): Resources {
//        val res = super.getResources()
//        if (allowFontScale()) {
//            return res
//        } else {
//            val displayMetrics = res.displayMetrics
//            val configuration = res.configuration
//            configuration.fontScale = 1.0f
//            //TODO updateConfiguration后DisplayMetrics的density和densityDpi会发生变化
//            res.updateConfiguration(configuration, displayMetrics)
//            return res
//        }
//    }

    override fun onResume() {
        super.onResume()
        initColor()
    }

    fun toggleBluetooth() {
        if (isCheckingBtEnabled) {
            return
        }
        NLog.e("start show bt dialog")
        val enableBtIntent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)
        enableBluetoothLauncher.launch(enableBtIntent)
        isCheckingBtEnabled = true
    }

    open fun registerReceiver() {
        // 注册网络变化广播
        val filter = IntentFilter()
        filter.addAction("android.net.conn.CONNECTIVITY_CHANGE")
        mNetworkChangeReceiver = Base_NetworkChangeReceiver()
        registerReceiver(mNetworkChangeReceiver, filter)
    }

    open fun unRegisterReceiver() {
        if (mNetworkChangeReceiver != null) {
            unregisterReceiver(mNetworkChangeReceiver)
            mNetworkChangeReceiver = null
        }
    }

    open fun initColor() {
        mThemeColor = if (!SettingUtil.getIsNightMode()) {
            SettingUtil.getColor()
        } else {
            resources.getColor(R.color.colorPrimary)
        }
        StatusBarUtil.setColor(this, mThemeColor, 0)
        if (this.supportActionBar != null) {
            this.supportActionBar?.setBackgroundDrawable(ColorDrawable(mThemeColor))
        }

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
//            window.statusBarColor = CircleView.shiftColorDown(mThemeColor)
//            // 最近任务栏上色
//            val tDesc = ActivityManager.TaskDescription(
//                    getString(R.string.app_name),
//                    BitmapFactory.decodeResource(resources, R.mipmap.ic_launcher),
//                    mThemeColor)
//            setTaskDescription(tDesc)
            if (SettingUtil.getNavBar()) {
                window.navigationBarColor = CircleView.shiftColorDown(mThemeColor)
            } else {
                window.navigationBarColor = Color.BLACK
            }
        }
    }

    open fun initColor(colorId: Int) {
        val statusBarColor = resources.getColor(colorId)
        StatusBarUtil.setColor(this, statusBarColor, 0)
        if (this.supportActionBar != null) {
            this.supportActionBar?.setBackgroundDrawable(ColorDrawable(statusBarColor))
        }

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            if (SettingUtil.getNavBar()) {
                window.navigationBarColor = CircleView.shiftColorDown(statusBarColor)
            } else {
                window.navigationBarColor = Color.BLACK
            }
        }
    }


    /**
     * 初始化 TipView
     */
    private fun initTipView() {
        mTipView = layoutInflater.inflate(R.layout.layout_network_tip, null)
        mTipMessage = mTipView.findViewById(R.id.tipMessage)
        mWindowManager = getSystemService(Context.WINDOW_SERVICE) as WindowManager
        mLayoutParams = WindowManager.LayoutParams(
            ViewGroup.LayoutParams.MATCH_PARENT,
            ViewGroup.LayoutParams.WRAP_CONTENT,
            WindowManager.LayoutParams.TYPE_APPLICATION,
            WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE or WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,
            PixelFormat.TRANSLUCENT
        )
        mLayoutParams.gravity = Gravity.TOP
        mLayoutParams.x = 0
        mLayoutParams.y = 0
        mLayoutParams.windowAnimations = R.style.anim_float_view // add animations
    }

    protected fun initToolbar(toolbar: Toolbar, homeAsUpEnabled: Boolean, title: String) {
        toolbar?.title = title
        setSupportActionBar(toolbar)
        supportActionBar?.setDisplayHomeAsUpEnabled(homeAsUpEnabled)
    }

    /**
     * Network Change
     */
    @Subscribe(threadMode = ThreadMode.MAIN)
    fun onNetworkChangeEvent(event: Base_NetworkChangeEvent) {
        hasNetwork = event.isConnected
        checkNetwork(event.isConnected)
    }

    /**
     * KCP Status Change
     */
    @Subscribe(threadMode = ThreadMode.MAIN)
    open fun onKcpChangeEvent(event: Base_KcpChangeEvent) {
        if (hasKcpNetwork != event.isConnected) {
            hasKcpNetwork = event.isConnected
            checkNetwork(event.isConnected, true)
        }
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    fun onMessageEventReceived(event: MessageEvent) {
        when (event.msgType) {
            TYPE_APP_SHOW_WAITING_DIALOG -> {
                val show = event.msgContent as Int
                NLog.e("TYPE_APP_SHOW_WAITING_DIALOG : $show")
                if (show == 1) {
                    showWaitingDialog(getString(R.string.dialog_content_ble_open))
                } else {
                    hideWaitingDialog()
                }
            }

            TYPE_APP_BLE_OPEN_DOOR_RESULT -> {
                val show = event.msgContent as String
                showResultDialog(show)
            }

            TYPE_APP_OPEN_BT -> {
                NLog.e("[MainActivity] >>>  打开蓝牙 ")
                toggleBluetooth()
            }

        }
    }

    private fun checkNetwork(isConnected: Boolean, isKcp: Boolean = false) {
        logInfo<NL_BaseActivity>("[jake] .. BaseActivity :  checkNetwork isConnected:$isConnected isKcp:$isKcp hasKcpNetwork:$hasKcpNetwork")
        if (isConnected) {
            doReConnected()
        }
    }

    override fun dispatchTouchEvent(ev: MotionEvent?): Boolean {
        if (ev?.action == MotionEvent.ACTION_UP) {
            val v = currentFocus
            // 如果不是落在EditText区域，则需要关闭输入法
            if (KeyBoardUtil.isHideKeyboard(v, ev)) {
                KeyBoardUtil.hideKeyBoard(this, v)
            }
        }
        return super.dispatchTouchEvent(ev)
    }

    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        when (item.itemId) {
            android.R.id.home -> {
                onBackPressed()
            }
        }
        return super.onOptionsItemSelected(item)
    }

    override fun onBackPressed() {
        super.onBackPressed()
        // Fragment 逐个出栈
        val count = supportFragmentManager.backStackEntryCount
        if (count == 0) {
            super.onBackPressed()
        } else {
            supportFragmentManager.popBackStack()
        }
    }

    override fun onPause() {
        super.onPause()
    }

    override fun onDestroy() {
        super.onDestroy()
        unRegisterReceiver()
        releaseToastDialog()
        if (mTipView != null && mTipView.parent != null) {
            mWindowManager.removeView(mTipView)
        }
        ToastUtils.cancel()
        if (useEventBus()) {
            EventBus.getDefault().unregister(this)
        }
    }

    private fun releaseToastDialog() {
        if (toastSettingDialog != null) {
            toastSettingDialog?.clearTask()
        }
    }

    private fun dismissToastDialog() {
        if (toastSettingDialog != null && toastSettingDialog?.isShowing == true) {
            toastSettingDialog?.dismiss()
        }
    }

    override fun finish() {
        super.finish()
        if (!this::mTipView.isInitialized) return

        if (mTipView.parent != null) {
            mWindowManager.removeView(mTipView)
        }
    }

    private val activityCallbacks: SparseArray<NL_OnActivityCallback?> by lazy { SparseArray(1) }
    open fun startActivityForResult(clazz: Class<out Activity>, callback: NL_OnActivityCallback?) {
        startActivityForResult(Intent(this, clazz), null, callback)
    }

    open fun startActivityForResult(intent: Intent, callback: NL_OnActivityCallback?) {
        startActivityForResult(intent, null, callback)
    }

    open fun startActivityForResult(
        intent: Intent,
        options: Bundle?,
        callback: NL_OnActivityCallback?
    ) {
        // 请求码必须在 2 的 16 次方以内
        val requestCode: Int = Random().nextInt(2.0.pow(16.0).toInt())
        activityCallbacks.put(requestCode, callback)
        startActivityForResult(intent, requestCode, options)
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        var callback: NL_OnActivityCallback?
        if ((activityCallbacks.get(requestCode).also { callback = it }) != null) {
            callback?.onActivityResult(resultCode, data)
            activityCallbacks.remove(requestCode)
            return
        }
        super.onActivityResult(requestCode, resultCode, data)
    }


    fun showOpenDoorResultDialog(event: OpenDoorResultBean) {
        logInfo<NL_BaseActivity>("[jake] .. BaseActivity :  onOpenDoorResultKcp : ${event.success}")
        dismissToastDialog()
        val openDoorResult = event.success
        val openDoorReason = event.reason

        val successStrVal = resources.getString(R.string.open_door_success_str)
        Log.e("jake", "[jake] >>> successStrVal : $successStrVal")
        val offlineStrVal = resources.getString(R.string.result_offline)
        val failedStrVal = resources.getString(R.string.open_door_failed_str)

        val resultVal = if (openDoorResult) successStrVal else {
            if (openDoorReason == "-1") {
                offlineStrVal
            } else {
                failedStrVal
            }
        }
        Log.e("jake", "openDoorResultStr : $resultVal")
        val drawable =
            if (openDoorResult) R.drawable.toast_success_green else R.drawable.toast_warning_yellow
        toastSettingDialog =
            ToastSettingDialog.Builder(this@NL_BaseActivity).tittle("").drawable(drawable)
                .message(resultVal).build()
        toastSettingDialog?.show()
        EventBus.getDefault().post(MessageEvent(TYPE_APP_SHOW_LOADING, false))
    }

    private fun showResultDialog(show: Int) {
        val successStrVal = resources.getString(R.string.open_door_success_str)

        val failedStrVal = resources.getString(R.string.open_door_failed_str)
        val timeOutStr = resources.getString(R.string.open_door_timeout_str)

        var resultVal = successStrVal
        var drawable = R.drawable.toast_success_green

        when (show) {

            1 -> {
                resultVal = successStrVal
                drawable = R.drawable.toast_success_green
            }

            2 -> {
                resultVal = timeOutStr
                drawable = R.drawable.toast_warning_yellow
            }

            else -> {
                resultVal = failedStrVal
                drawable = R.drawable.toast_warning_yellow
            }

        }
        Log.e("jake", "[jake] >>> successStrVal : $resultVal")

        toastSettingDialog =
            ToastSettingDialog.Builder(this@NL_BaseActivity).tittle("").drawable(drawable)
                .message(resultVal).build()
        toastSettingDialog?.show()
        EventBus.getDefault().post(MessageEvent(TYPE_APP_SHOW_LOADING, false))
    }

    private fun showResultDialog(show: String) {
        val successStrVal = resources.getString(R.string.open_door_success_str)

        var resultVal = successStrVal
        var drawable = R.drawable.toast_success_green
        when (show) {

            "1" -> {
                resultVal = successStrVal
                drawable = R.drawable.toast_success_green
            }

            else -> {
//                resultVal = show
                resultVal = resources.getString(R.string.open_door_failed_str)
                drawable = R.drawable.toast_failed_red
            }

        }
        Log.e("jake", "[jake] >>> successStrVal : $resultVal")

        toastSettingDialog =
            ToastSettingDialog.Builder(this@NL_BaseActivity).tittle("").drawable(drawable)
                .message(resultVal).build()
        toastSettingDialog?.show()
        EventBus.getDefault().post(MessageEvent(TYPE_APP_SHOW_LOADING, false))
    }

    private var mWaitProgressDialog: ProgressDialog? = null
    open fun showSnackBar(message: String) {
        Snackbar.make(this.window.decorView, message, Snackbar.LENGTH_LONG).show()
    }

    private fun showWaitingDialog(msg: String) {
//        hideWaitingDialog()
        if (mWaitProgressDialog?.isShowing == true) {
            return
        }
        mWaitProgressDialog = DialogUtil.getWaitDialog(this, msg)
        if (mWaitProgressDialog != null) {
            NLog.e(">>>> showWaitingDialog")
//            mWaitProgressDialog?.setProgressStyle(ProgressDialog.STYLE_SPINNER)
            mWaitProgressDialog?.show()

        } else {
            NLog.e(">>>> showWaitingDialog failed....")
        }
    }

    private fun hideWaitingDialog() {
        if (mWaitProgressDialog?.isShowing == true) {
            NLog.e("<<<<< hideWaitingDialog")
            mWaitProgressDialog?.dismiss()
            mWaitProgressDialog = null
        }
    }


}
